// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu, jhkim

#include "coin2/strategy/linear_model/logic_factory.h"

#include <memory>

#include "coin2/exchange/base/symbology/product_encyclopedia.h"
#include "coin2/strategy/linear_model/agg.h"
#include "coin2/strategy/linear_model/agg2.h"
#include "coin2/strategy/linear_model/logic.h"
#include "coin2/strategy/linear_model/focus.h"
#include "coin2/strategy/linear_model/focus2.h"
#include "coin2/strategy/linear_model/focus3.h"
#include "coin2/strategy/linear_model/focus_midfreq.h"
#include "presto/quant/symbology/symbol.h"

namespace coin2::strategy::linear_model {

std::unique_ptr<LinearModelLogic> LmLogicFactory::CreateNewLmLogic(
    const MarketExchangeApi& mea,
    const ::coin2::exchange::base::symbology::IProduct& target_product,
    const ::presto::Symbol* target_symbol,
    LmProductConfig lm_product_config,
    ::coin2::exchange::base::symbology::ProductEncyclopedia* product_cache,
    const ::presto::SymbolManager* symbol_manager,
    std::shared_ptr<::fastfeature::KlineInfoProto> kline_info = nullptr) {
  if (lm_product_config.has_agg_config()) {
    switch (lm_product_config.agg_config().ver()) {
      case 0:
        return std::unique_ptr<LinearModelLogic>(
            new LmAggLogic(mea, target_product, target_symbol, lm_product_config, product_cache));
      case 1:
        NOTREACHED() << "ver=1 is deprecated";
        return std::unique_ptr<LinearModelLogic>(nullptr);
      case 2:
        return std::unique_ptr<LinearModelLogic>(
            new LmAggLogic2(mea, target_product, target_symbol, lm_product_config, product_cache));
    }
  } else if (lm_product_config.has_focus_config()) {
    if (lm_product_config.focus_config().has_buy_threshold_bps() &&
        lm_product_config.focus_config().has_buy_threshold_bps_add()) {
      lm_product_config.mutable_focus_config()->set_buy_threshold_bps(
          lm_product_config.focus_config().buy_threshold_bps() +
          lm_product_config.focus_config().buy_threshold_bps_add());
    }
    switch (lm_product_config.focus_config().ver()) {
      case 0:
        return std::unique_ptr<LinearModelLogic>(
            new LmFocusLogic(
              mea,
              target_product,
              target_symbol,
              lm_product_config,
              product_cache,
              symbol_manager));
      case 1:
        NOTREACHED() << "ver=1 is deprecated";
        return std::unique_ptr<LinearModelLogic>(nullptr);
      case 2:
        return std::unique_ptr<LinearModelLogic>(
            new LmFocusLogic2(
              mea,
              target_product,
              target_symbol,
              lm_product_config,
              product_cache,
              symbol_manager,
              kline_info));
      case 3:
        return std::unique_ptr<LinearModelLogic>(
            new LmFocusLogic3(
              mea,
              target_product,
              target_symbol,
              lm_product_config,
              product_cache,
              symbol_manager,
              kline_info));
    }
  } else if (lm_product_config.has_focus_midfreq_config()) {
    return std::unique_ptr<LinearModelLogic>(
            new LmFocusMidfreqLogic(
                mea,
                target_product,
                target_symbol,
                lm_product_config,
                product_cache,
                symbol_manager,
                kline_info));
  } else if (lm_product_config.search_focus_midfreq_config_size() > 0) {
    return std::unique_ptr<LinearModelLogic>(
            new SearchLmFocusMidfreqLogic(
                mea,
                target_product,
                target_symbol,
                lm_product_config,
                product_cache,
                symbol_manager,
                kline_info));
  } else {
    NOTREACHED() << "[LmLogicFactory] unknown strategy_type: " << lm_product_config.DebugString();
  }
  return {};
}

}  // namespace coin2::strategy::linear_model
